/*
   couchshowstops.js: it's magic
   $Id$

   Copyright 2011 Portland Transport

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   Authors:
   Matt Conway: main code

*/


SERVER = "http://transitappliance.couchone.com"; // No trailing slash
DB = 'transit_stops_loading'; // no leading or trailing slashes
AGENCIES_DB = 'agencies'; // ditto

// Projections
DB_PROJ = 'EPSG:4326'; // WGS 1984 lat/lon
MAP_PROJ = 'EPSG:900913'; // Spherical Mercator

ZOOM_THRESHOLD = 13; // At levels below this, stops won't be shown.

// Deal with projection nonsense
function lonlat(lon, lat) {
    return new OpenLayers.LonLat(lon, lat).transform(
        new OpenLayers.Projection(DB_PROJ),
        map.getProjectionObject()
    );
}

// Much simpler projection to deal with, lon/lat instead of meters
function toWGS1984(object) {
    return object.transform(
	map.getProjectionObject(),
	new OpenLayers.Projection(DB_PROJ)
    );
}

// Draw the bubble/identify tool
function handleSelect (stop) {
    // Build the bubble
    var popupLonLat = new OpenLayers.LonLat(stop.geometry.x, stop.geometry.y);

    // Build the html
    var v = stop.attributes.doc;
    var stopHTML = '';
    stopHTML += '<h3>' + v.stop_name + '</h3>';
    stopHTML += '<table class="stopinfo">';
    stopHTML += '<tr><td>Agency</td><td>' + v.agency + '</td></tr>';
    stopHTML += '<tr><td>Stop ID</td><td>' + v.stop_id + '</td></tr>';
    stopHTML += '<tr><td>AVL ID</td><td>' + v.avl_id + '</td></tr>';
    stopHTML += '<tr><td>Stop Code</td><td>' + v.stop_code + '</td></tr>';
    stopHTML += '<tr><td>Dir.</td><td>' + v.direction + '</td></tr>';
    stopHTML += '<tr><td>Name</td><td>' + v.stop_name + '</td></tr>';
    stopHTML += '<tr><td>Desc.</td><td>' + v.stop_desc + '</td></tr>';
    stopHTML += '</table>';
    // Go to the DBPATH, then up one directory
    // If it's a CouchApp, just go up one dir
    stopHTML += '<a target="_blank" href="' + SERVER + '/_utils/document.html?' + DB + '/' + v._id + '">Look this record up in the database</a>'

    // Can't use hash, does not work.
    var bubble = new OpenLayers.Popup.FramedCloud (
	"bubble", // id
	popupLonLat, // lonlat
	null, // size
	stopHTML, // HTML
	null, // anchor
	true, // close box
	null // close bx callback
    );

    // Exclusive popup
    map.addPopup(bubble, true);
}

// Add the copyright notice for a particular agency to the copyright area
function addCopyright(e) {
    console.log('adding stop');
    stop = e.feature;
    // Thanks JS for no ... in ... operation.
    if (displayedAgencies.indexOf(stop.attributes.doc.agency) == -1) {
	console.log('Showing copyright data');
	
	if (!(stop.attributes.doc.agency in agencies)) {
	    // Cache the agency
	    // Cache the rights notice and add it
	    console.log('Making request for agency ' + stop.attributes.doc.agency);
	    $.ajax({
		url: SERVER + '/' + AGENCIES_DB + '/' + stop.attributes.doc.agency,
		dataType: 'jsonp', // TODO: fix CouchDB to allow CORS		
		success: function (agency) {
		    console.log('request succeeded');
		    // Cache it
		    agencies[agency._id] = agency;
		    
		    // Log it
		    console.log('Copyright info for agency ' + agency.agency_name + ': ' + agency.rights_notice);

		    // Display it
		    $('#rights').append(
			'<div class="right">' + agency.rights_notice + '</div>');
		}
	    });

	}
	else {
	    // Add the agency
	    $('#rights').append(
			'<div class="right">' + agencies[stop.attributes.doc.agency].rights_notice + '</div>');
	}

	// Remember it so we don't show it twice
	displayedAgencies.push(stop.attributes.doc.agency);
    }
}

function mapMoved() {
    if (map.getZoom() >= ZOOM_THRESHOLD) {
	stopLayer.display(true); // Display the layer
	$('#stops_shown').fadeIn(1000);
    }
    else {
	stopLayer.display(false); // Undisplay the layer
	$('#stops_shown').fadeOut(600);
    }
}

function init() {

    // Create a map
    map = new OpenLayers.Map('map', {
	projection: MAP_PROJ // spherical mercator
    });

    // Add the base layer (OpenStreetMap)
    osmLayer = new OpenLayers.Layer.OSM('OpenStreetMap base map');
    map.addLayer(osmLayer);
    map.setBaseLayer(osmLayer);

    map.setCenter(lonlat(-122.33862983038, 37.660818654343), 9);

    $('#nominatim_form').submit(nominatim);

    // Add the agencies db
    agencies = [];

    // Add the list of currently displayed copyrights
    displayedAgencies = [];

    stopLayer = new OpenLayers.Layer.Vector('Stops', {
	strategies: [new OpenLayers.Strategy.BBOX()],
	projection: DB_PROJ, // Do this here instead of in format so that bboxes
	// will also be translated to WGS 1984
	maxResolution: 40,
	protocol: new OpenLayers.Protocol.HTTP({
	    url: SERVER + '/' + DB + '/_design/geo/_spatiallist/geojson/points',
	    format: new OpenLayers.Format.GeoJSON()
	}),
	transitionEffect: 'none',
	styleMap: new OpenLayers.StyleMap(
            OpenLayers.Util.applyDefaults(
                {externalGraphic: "stopIcon.gif", graphicOpacity: 1},
                OpenLayers.Feature.Vector.style["default"])
	)
    });

    // Add copyrights as features are added
    stopLayer.events.on({
	'featureadded': addCopyright
    });
    
    map.addLayer(stopLayer);
    
    // Hide it by default
    stopLayer.display(false);

    // Set up the selector
    var stopControl = new OpenLayers.Control.SelectFeature(stopLayer, {
	onSelect: handleSelect,
	highlightOnly: true
    });
    map.addControl(stopControl);
    stopControl.activate();

    // Add the event listener
    map.events.on({
	"moveend": mapMoved
    });

    // Fire off a mapMoved event to determine whether or not to fetch the data
    //mapMoved();
}

// When we search for a location, do it
function nominatim(e) {
    e.preventDefault();

    // Clear it out
    $('.nominatim_result').remove();
    $('.nominatim_err').remove();

    $.ajax({
	url: 'http://nominatim.openstreetmap.org/search',
	data: {format: 'json', q: $('#nominatim_input').val()},
	dataType: 'json',
	success: function (data) {
	    if (data.length == 0) {
		$('#nominatim_results').append('<div class="nominatim_err">No results found for query ' + $('#nominatim_input').val() + '</div>');
		$('#nominatim_results').slideDown();
	    }

	    else if (data.length == 1) {
		$('#nominatim_results').slideUp(); // In case it isn't
		// (repeated searches)
		centerMap(data[0].lon, data[0].lat);
	    }

	    else {
		data.forEach(function (place) {
		    thediv  = '<div class="nominatim_result">';
		    thediv += '<a href="#" onclick="centerMap(' + place.lon + ',' + place.lat + ')">';
		    thediv += place.display_name + '</a>';
		    $('#nominatim_results').append(thediv);
		});
		$('#nominatim_results').slideDown();
	    }
	}
    });
}

// Center the map
function centerMap(lon, lat) {
    // Hide the results
    $('#nominatim_results').slideUp();
    $('#nominatim_result').remove();
    map.setCenter(lonlat(lon, lat), 15)
}